package com.siyoumi.app.modules.user.service;

import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.siyoumi.app.entity.SysUser;
import com.siyoumi.app.entity.WxUserLogin;
import com.siyoumi.app.modules.user.vo.SysUserAudit;
import com.siyoumi.app.modules.user.vo.SysUserAdd;
import com.siyoumi.app.modules.user.vo.SysUserEdit;
import com.siyoumi.app.modules.user.vo.SysUserEditPwd;
import com.siyoumi.app.service.SysUserService;
import com.siyoumi.app.service.WxUserLoginService;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import com.siyoumi.validator.annotation.HasAnyText;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;

//系统用户
@Slf4j
@Service
public class SvcSysUser {
    static public SvcSysUser getBean() {
        return XSpringContext.getBean(SvcSysUser.class);
    }

    static public SysUserService getApp() {
        return SysUserService.getBean();
    }

    public JoinWrapperPlus<SysUser> listQuery(InputData inputData) {
        String phone = inputData.input("phone");
        String uid = inputData.input("uid");

        JoinWrapperPlus<SysUser> query = getApp().join();
        query.eq("user_x_id", XHttpContext.getX());

        if (XStr.hasAnyText(phone)) { //手机号
            query.eq("user_phone", phone);
        }
        if (XStr.hasAnyText(uid)) { //uid
            query.eq("user_id", uid);
        }

        return query;
    }

    public SysUser getEntity(String id) {
        return XRedis.getBean().getAndSetData(getApp().getEntityCacheKey(id), k -> {
            return getApp().loadEntity(id);
        }, SysUser.class);
    }

    public SysUser getOrNew(SysUserAdd data) {
        SysUser entityUser = SvcSysUser.getBean().getUserByPhone(data.getUser_phone());
        if (entityUser == null) { //手机号未注册，新建
            SysUser entityUserUpdate = new SysUser();
            XBean.copyProperties(data, entityUserUpdate);
            entityUserUpdate.setUser_x_id(XHttpContext.getX());
            if (XStr.hasAnyText(data.getId())) {
                entityUserUpdate.setUser_id(data.getId());
            } else {
                entityUserUpdate.setUser_id(XApp.getStrID());
            }

            SvcSysUser.getApp().save(entityUserUpdate);

            entityUser = SvcSysUser.getBean().getUserByPhone(data.getUser_phone());
        }

        return entityUser;
    }

    public SysUser getUserByOpenid(String openid) {
        JoinWrapperPlus<SysUser> query = getApp().join();
        query.eq("user_openid", openid)
                .eq("user_x_id", XHttpContext.getX());
        return getApp().first(query);
    }

    public SysUser getUserByPhone(String phone) {
        JoinWrapperPlus<SysUser> query = getApp().join();
        query.eq("user_phone", phone)
                .eq("user_x_id", XHttpContext.getX());
        return getApp().first(query);
    }

    public SysUser getUserByUsername(String username) {
        JoinWrapperPlus<SysUser> query = getApp().join();
        query.eq("user_username", username)
                .eq("user_x_id", XHttpContext.getX());
        return getApp().first(query);
    }

    public SysUser getUserByPhoneAndUsername(String phoneOrUsername) {
        JoinWrapperPlus<SysUser> query = getApp().join();
        query.eq("user_x_id", XHttpContext.getX()).and(q -> {
            q.eq("user_phone", phoneOrUsername).or().eq("user_username", phoneOrUsername);
        });
        return getApp().first(query);
    }

    public String getOpenid(String uid) {
        return getOpenid(uid, false);
    }

    /**
     * 获取最新登陆过的openid
     *
     * @param uid
     */
    public String getOpenid(String uid, Boolean throwEx) {
        SysUser entity = getEntity(uid);
        if (entity == null) {
            if (throwEx) {
                XValidator.err(EnumSys.SYS.getR("缺少openid，" + uid));
            }
            return null;
        }

        return entity.getUser_openid();
        //JoinWrapperPlus<WxUserLogin> query = listLoginQuery();
        //query.select("wulogin_openid");
        //query.eq("wulogin_uid", uid);
        //query.orderByDesc("wulogin_id");
        //
        //Map<String, Object> mapItem = WxUserLoginService.getBean().firstMap(query);
        //if (mapItem == null) {
        //    if (throwEx) {
        //        XValidator.err(EnumSys.SYS.getR("缺少openid，" + uid));
        //    }
        //    return null;
        //}
        //
        //return (String) mapItem.get("wulogin_openid");
    }

    /**
     * 已登陆
     *
     * @param entityLogin
     */
    public Boolean isLogin(WxUserLogin entityLogin) {
        if (entityLogin == null) {
            return false;
        }

        return entityLogin.getWulogin_state() == 1;
    }

    /**
     * 根据openid，获取登录中记录
     */
    public WxUserLogin getLogin(String openid) {
        JoinWrapperPlus<WxUserLogin> query = listLoginQuery();
        query.eq("wulogin_openid", openid);

        return WxUserLoginService.getBean().first(query);
    }

    /**
     * 已登录状态，所有变为未登录
     *
     * @param openid
     */
    public void updateLoginState0(String openid, String uid) {
        UpdateChainWrapper<WxUserLogin> query = WxUserLoginService.getBean().update()
                .set("wulogin_state", 0)
                .eq("wulogin_state", 1);
        if (XStr.hasAnyText(uid)) {
            query.eq("wulogin_uid", uid);
        } else {
            query.eq("wulogin_openid", openid);
        }

        query.update();
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<WxUserLogin> listLoginQuery() {
        JoinWrapperPlus<WxUserLogin> query = WxUserLoginService.getBean().join();
        query.eq("wulogin_x_id", XHttpContext.getX());

        return query;
    }


    /**
     * 用户是否有效
     *
     * @param entity
     */
    public XReturn valid(SysUser entity) {
        if (entity == null) {
            return EnumSys.ERR_UID.getR("用户不存在");
        }
        if (entity.getUser_enable() == 0) {
            return EnumSys.ERR_UID.getR("用户审核中");
        }
        if (entity.getUser_enable() != 1) {
            return EnumSys.ERR_UID.getR("用户已失效");
        }

        return EnumSys.OK.getR();
    }


    /**
     * 编辑用户信息
     *
     * @param vo
     */
    public XReturn userEdit(SysUserEdit vo) {
        SysUser entity = getApp().getEntity(vo.getUid());
        XValidator.err(valid(entity));

        SysUser entityUpdate = new SysUser();
        XBean.copyProperties(vo, entityUpdate);
        getApp().saveOrUpdatePassEqualField(entity, entityUpdate);

        return EnumSys.OK.getR();
    }

    /**
     * 编辑用户密码
     *
     * @param vo
     */
    public XReturn userEditPwd(SysUserEditPwd vo) {
        SysUser entity = getApp().getEntity(vo.getUid());
        XValidator.err(valid(entity));

        String pwdOldDec = XStr.base64Dec(vo.getUser_pwd_old());
        log.debug("pwd_old_dec: {}", pwdOldDec);

        String encPwdOld = XApp.encPwd(entity.getUser_x_id(), XStr.base64Dec(vo.getUser_pwd_old()));
        log.debug("pwd: {}", entity.getUser_pwd());
        if (!encPwdOld.equals(entity.getUser_pwd())) {
            return XReturn.getR(20148, "旧密码错误");
        }

        SysUser entityUpdate = new SysUser();
        XBean.copyProperties(vo, entityUpdate);
        entityUpdate.setUser_pwd(XApp.encPwd(entity.getUser_x_id(), XStr.base64Dec(vo.getUser_pwd())));
        getApp().saveOrUpdatePassEqualField(entity, entityUpdate);

        return EnumSys.OK.getR();
    }

    /**
     * 审核
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class)
    public XReturn audit(SysUserAudit vo) {
        List<SysUser> listUser = getApp().get(vo.getIds());
        for (SysUser entity : listUser) {
            if (Objects.equals(entity.getUser_enable(), vo.getEnable())) {
                continue;
            }

            SysUser entityUpdate = new SysUser();
            entityUpdate.setUser_id(entity.getKey());
            entityUpdate.setUser_enable(vo.getEnable());
            entityUpdate.setUser_enable_date(XDate.now());
            getApp().updateById(entityUpdate);
        }
        return EnumSys.OK.getR();
    }

    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

        getApp().delete(ids);
        //需要删除登陆表记录
        {
            JoinWrapperPlus<WxUserLogin> query = WxUserLoginService.getBean().join();
            query.eq("wulogin_uid", ids);
            WxUserLoginService.getBean().remove(query);
        }


        return r;
    }

    /**
     * 默认密码
     */
    static public String defPwd() {
        return XDate.format(XDate.today(), "yyyyMMdd");
    }

    /**
     * 默认密码123456
     */
    static public String defPwdNum() {
        return XDate.format(XDate.today(), "123456");
    }

    static public String tempPhone(String val) {
        return "TEMP." + val;
    }

    /**
     * 重置密码
     *
     * @param ids
     */
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn resetPwd(List<String> ids) {
        List<SysUser> listUser = getApp().get(ids);
        for (SysUser entity : listUser) {
            SysUser entityUpdate = new SysUser();
            entityUpdate.setUser_id(entity.getKey());
            entityUpdate.setUser_pwd(XApp.encPwd(XHttpContext.getX(), defPwd()));
            getApp().updateById(entityUpdate);
        }
        return EnumSys.OK.getR();
    }
}
